package com.huajx.tb.handler;

import com.huajx.core.Hboot;
import com.huajx.core.config.HbootConfig;
import com.huajx.core.handler.HandlerAdapter;
import com.huajx.core.kit.AsyncHttpClientKit;
import com.huajx.core.kit.HttpKit;
import com.huajx.core.message.RequestMessage;
import com.huajx.core.util.MessageKit;
import com.huajx.tb.config.TianboConfig;
import com.huajx.tb.dto.NengLongMessage;
import com.huajx.tb.exception.NengLongTcpException;
import com.huajx.util.StrUtil;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Map;

/**
 * 抽象类，处理能龙协议数据
 *
 * @author: lisa 叶新华
 * @create: 2019-08-28 17:56
 */
public abstract class AbstractNengLongHandler implements HandlerAdapter {
    protected final static Logger logger = LoggerFactory.getLogger(AbstractNengLongHandler.class);
    // 响应 同步帧 标识
    protected final static String RETURN_COMMAND = "JTP";
    //    protected final static String SERVER_URL = "http://wx.52ycm.com/wechat";
    protected final static String SERVER_URL = Hboot.config(HbootConfig.class).getRemoteUrl();//"http://mainhost:8080/wechat";
    //protected final static String SERVER_URL = "http://127.0.0.1:8080/wechat";

    protected final static TianboConfig config = Hboot.config(TianboConfig.class);

    protected final static String[] serverUrls = getServerUrls();
    private static int serverUrlIndex = 0;

    /**
     * 从配置文件中获取服务器请求URLs,
     * 数组表示是集群，在配置文件中，以逗号分隔
     *
     * @return 服务器请求URLs
     */
    private static String[] getServerUrls() {
        String apiUrl = config.getApiUrl();

        String[] urls = apiUrl.split(",");
        return urls;
    }

    /**
     * 获取远程访问URL
     *
     * @param url 服务器路径
     * @return 服务URL
     */
    protected String getServerUrl(String url) {

        if (url.startsWith("http://") || url.startsWith("//")) {
            return url;
        }

        int len = serverUrls.length;

        if (serverUrlIndex >= len) {
            serverUrlIndex = 0;
        }

        String surl = serverUrls[serverUrlIndex];

//        logger.info("当前请求URL:{}， 第{}", surl, serverUrlIndex);

        serverUrlIndex++;

        if (StrUtil.isBlank(url)) {
            return surl;
        } else {
            return surl + url;
        }
    }

    /**
     * 获取消息对象，进行相应的处理
     *
     * @param message 消息对象
     * @return 消息对象
     */
    protected NengLongMessage getMessage(Object message) {
        if (message == null) {
            throw new NengLongTcpException("无包体");
        } else if (!(message instanceof NengLongMessage)) {
            throw new NengLongTcpException("消息未转换");
        }

        return (NengLongMessage) message;
    }

    /**
     * 空响应
     * @param session 会话
     */
    @Override
    public void render(IoSession session) {

    }

    /**
     * 应答语法
     * 后台拼接好包长+功能号+包体+较验码
     *
     * @param session 会话
     * @param bytes   响应包
     * @param content 内容
     */
    protected void render(IoSession session, byte[] bytes, String content) {
        String commonStr = MessageKit.getStr(bytes, 3, 23); // 公共部分 序号 + 协议版本号 + 机器号
        StringBuilder sb = new StringBuilder();
        sb.append(RETURN_COMMAND).append(commonStr).append(content);
        logger.info("返回命令, {}", sb);
        session.write(sb.toString());
    }

    /**
     * 应答语法
     * <p>
     * 后台未拼接，直接返回包体
     *
     * @param session 会话
     * @param dto     消息对象
     * @param content 包体
     */
    protected void render(IoSession session, NengLongMessage dto, String content) {
        byte[] bytes = dto.getBody();
        String m = MessageKit.getStr(bytes, 3, 23);

        int len = null == content ? 2 : content.length() + 2;
        String lenHex = MessageKit.intToHex(len, '0', 4);

        String command = dto.getCommand();
        String checksum = MessageKit.checksum(command + content);

        StringBuilder sb = new StringBuilder();
        sb.append(RETURN_COMMAND).append(m).append(lenHex).append(command).append(content).append(checksum);
        logger.info("返回命令, {}", sb);
        session.write(sb.toString());
    }

    /**
     * 应答语法
     * @param request 请求
     * @param content 噢应内容
     */
    protected void render(RequestMessage request, String content) {
        NengLongMessage dto = getMessage(request.getMessage());
        IoSession session = request.getSession();
        render(session, dto, content);
    }

    protected void asyncPost(String controllerKey, Map<String, Object> paras, byte[] bytes, RequestMessage request, AsyncHttpClientKit.StringFutureCallback callback) {
        controllerKey = getServerUrl(controllerKey);

        AsyncHttpClientKit.post(controllerKey, paras, content -> {
            if (callback == null) {
//                render(request.getSession(), bytes, content);
            } else {
                callback.success(content);
            }
        });
    }

    protected Object post(String controllerKey, Map<String, String> paras) throws IOException {
        controllerKey = getServerUrl(controllerKey);

        return HttpKit.post(controllerKey, paras);
    }
}
